﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using GeneralClasses;
using System.Globalization;


namespace Algorithm
{
    public class Single_Schedule : System.IComparable
    {

        // Constants to prevent stray "100s"
        public const int REALLY_BAD_SCORE = -10000;
        public const int SCORE_BASE = 100;
        public const int SHIFT = 8;

        ArrayList TheArray = new ArrayList();
        public static Random TheSeed = new Random((int)DateTime.Now.Ticks);
        //ScheduleData data = new ScheduleData();
        ScheduleData data;
        double grade;

        #region CONSTRUCTOR
        public Single_Schedule(long length, object temp_min, object temp_max, ScheduleData temp_data)
        {

            // Create array of integers representing a schedule
            try
            {
                data = temp_data;
                int min, max = 0;
                min = (int)temp_min;
                max = (int)temp_max;
                for (int i = 0; i < length; i++)
                {
                    int nextValue = (int)GenerateGeneValue(min, max);
                    TheArray.Add(nextValue);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} Exception caught.", e);
                UTIL.sayDebug(e);
                throw e;
            }

        }//Single_Schedule(long,object,object)
        #endregion
        #region GENERATEGENE
        public object GenerateGeneValue(object min, object max)
        {
            // Generate random gene values for schedule array
            return TheSeed.Next((int)min, (int)max);
        }//GenerateGeneValue(object,object)
        #endregion
        #region HEURISTIC
        public double Heuristic(/* WEIGHTS NEEDED*/)
        {
            try
            {
                // Get information that is necessary for the tests in the Heuristic portion
                int num_departments = data.Departments.Count;
                int department_nurse_total = 0;
                //int shifts = data.Shifts.Count;
                int shifts = 3;
                for (int k = 0; k < num_departments; k++)
                {
                    department_nurse_total += data.Departments[k].PeopleNeeded;
                }//for

                int day = department_nurse_total * shifts;
                int shift = (day / shifts) / num_departments;
                int temp_nurse = 0;
                int pivot = 0;
                int loop_count = 0;
                int shift_pref_violated = 0;
                int dept_pref_violated = 0;
                int hour_pref_violated = 0;
                int department_count = 0;
                List<Department> allDepts = new List<Department>();// data.Persons[temp_nurse].getAllDepartments();
                allDepts = data.Departments;
                int[] hoursScheduled = new int[day * data.NumDays];
                int temp_int = 0;

                // Check to see if the nurse's scheduled department is his or her preferred department.
                // Points will be subtracted from the heuristic score if the nurse is not scheduled for
                // his or her preferred department

                IEnumerator Enum = TheArray.GetEnumerator();
                Enum.Reset();

                List<Person> nurse_list = data.Persons;

                while (Enum.MoveNext())
                {
                    temp_nurse = (int)Enum.Current;
                    List<int> prefDept = new List<int>();
                    //prefDept = nurse_list[temp_nurse].loadAssignedDepartments();
                    prefDept = nurse_list[temp_nurse].DepartmentTableIDs;
                    hoursScheduled[temp_nurse] += SHIFT;

                    if (hoursScheduled[temp_nurse] > data.Persons[temp_nurse].ApproxHours)
                    {
                        hour_pref_violated++;
                    }


                    if (prefDept[0] != allDepts[department_count].DepartmentID)
                    {
                        dept_pref_violated++;
                    }

                    department_count = (department_count + 1) % num_departments;
                }

                Enum.Reset();

                // Check to make sure no nurse is working a back-to-back shift
                while (pivot < TheArray.Count)
                {
                    if (shifts == 3)
                    {

                        ArrayList shift1 = TheArray.GetRange(pivot, shift);
                        pivot = pivot + shift;
                        ArrayList shift2 = TheArray.GetRange(pivot, shift);
                        pivot = pivot + shift;
                        ArrayList shift3 = TheArray.GetRange(pivot, shift);
                        pivot = pivot + shift;

                        if (loop_count != 0)
                        {
                            temp_int = pivot - shift;
                            ArrayList prev = TheArray.GetRange(temp_int, shift);
                            shift_pref_violated += shifts3(loop_count, prev, shift1, shift2, shift3);
                        }
                        else
                        {
                            shift_pref_violated += shifts3(loop_count, null, shift1, shift2, shift3);
                        }

                        loop_count++;
                    }

                    else if (shifts == 2)
                    {

                        ArrayList shift1 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;
                        ArrayList shift2 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;

                        if (loop_count != 0)
                        {
                            ArrayList prev = TheArray.GetRange(pivot, pivot + shift);
                            shift_pref_violated += shifts2(loop_count, prev, shift1, shift2);
                        }
                        else
                        {
                            shift_pref_violated += shifts2(loop_count, null, shift1, shift2);
                        }

                        loop_count++;
                    }

                    else if (shifts == 4)
                    {
                        ArrayList shift1 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;
                        ArrayList shift2 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;
                        ArrayList shift3 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;
                        ArrayList shift4 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;

                        if (loop_count != 0)
                        {
                            ArrayList prev = TheArray.GetRange(pivot, pivot + shift);
                            shift_pref_violated += shifts4(loop_count, prev, shift1, shift2, shift3, shift4);
                        }
                        else
                        {
                            shift_pref_violated += shifts4(loop_count, null, shift1, shift2, shift3, shift4);
                        }
                    }

                    else if (shifts == 5)
                    {
                        ArrayList shift1 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;
                        ArrayList shift2 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;
                        ArrayList shift3 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;
                        ArrayList shift4 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;
                        ArrayList shift5 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;

                        if (loop_count != 0)
                        {
                            ArrayList prev = TheArray.GetRange(pivot, pivot + shift);
                            shift_pref_violated += shifts5(loop_count, prev, shift1, shift2, shift3, shift4, shift5);
                        }
                        else
                        {
                            shift_pref_violated += shifts5(loop_count, null, shift1, shift2, shift3, shift4, shift5);
                        }
                    }
                }

                return 0 - Math.Abs(((shift_pref_violated * SCORE_BASE) - (dept_pref_violated * SCORE_BASE) - (hour_pref_violated * SCORE_BASE)));
            }
            catch (Exception e)
            {
                // Console.WriteLine("{0} Exception caught.", e);
                //  return REALLY_BAD_SCORE;
                UTIL.sayDebug(e);
                throw e;
            }

        }//Heuristic
        #endregion

        #region FITNESS
        public double CalculateFitness(double heuristic_score /* WEIGHTS NEEDED */)
        {

            try
            {
                // Get data needed to calculate fitness

                //ScheduleData data = new ScheduleData();
                DateTime start_date = data.StartDate;

                List<Person> nurse_list = data.Persons;

                // Assumes shift = 3
                int shifts = 3;
                int people = 0;
                for (int i = 0; i < data.Departments.Count; i++)
                {
                    people += data.Departments[i].PeopleNeeded;
                }
                // Assumes that every department has the same number of shifts

                //int day = data.Departments.Count * data.Departments[0].Shifts.Count * people;
                //int shift = day / data.Departments[0].Shifts.Count;
                int day = shifts * people;
                int shift = (day / shifts) / data.Departments.Count;
                int pivot = 0;
                int day_count = 0;
                int day_of_week_count = 0;

                int days_violated = 0;

                string[] days_of_week = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

                switch (data.StartDate.DayOfWeek.ToString())
                {
                    case "Sunday":
                        day_of_week_count = 0;
                        break;
                    case "Monday":
                        day_of_week_count = 1;
                        break;
                    case "Tuesday":
                        day_of_week_count = 2;
                        break;
                    case "Wednesday":
                        day_of_week_count = 3;
                        break;
                    case "Thursday":
                        day_of_week_count = 4;
                        break;
                    case "Friday":
                        day_of_week_count = 5;
                        break;
                    case "Saturday":
                        day_of_week_count = 6;
                        break;
                    default:
                        day_of_week_count = 0;
                        break;
                }

                // Call a function to evaluate fitness based on how many shifts there are in a day
                while (pivot < TheArray.Count)
                {
                    if (shifts == 3)
                    {
                        ArrayList shift1 = TheArray.GetRange(pivot, shift);
                        pivot = pivot + shift;
                        ArrayList shift2 = TheArray.GetRange(pivot, shift);
                        pivot = pivot + shift;
                        ArrayList shift3 = TheArray.GetRange(pivot, shift);
                        pivot = pivot + shift;

                        days_violated += days3(start_date, day_count, day_of_week_count, shift1, shift2, shift3, nurse_list);

                        day_count++;
                        day_of_week_count = (day_of_week_count + 1) % 7;
                        //shift1.Clear();
                        //shift2.Clear();
                        //shift3.Clear();
                    }
                    else if (data.Shifts.Count == 2)
                    {
                        ArrayList shift1 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;
                        ArrayList shift2 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;

                        days_violated += days2(start_date, day_count, day_of_week_count, shift1, shift2);

                        day_count++;
                        day_of_week_count = (day_of_week_count + 1) % 7;
                        shift1.Clear();
                        shift2.Clear();

                    }

                    else if (data.Shifts.Count == 4)
                    {
                        ArrayList shift1 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;
                        ArrayList shift2 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;
                        ArrayList shift3 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;
                        ArrayList shift4 = TheArray.GetRange(pivot, pivot + shift);
                        pivot = pivot + shift;

                        days_violated += days4(start_date, day_count, day_of_week_count, shift1, shift2, shift3, shift4);

                        day_count++;
                        day_of_week_count = (day_of_week_count + 1) % 7;
                        shift1.Clear();
                        shift2.Clear();
                        shift3.Clear();
                        shift4.Clear();

                    }
                }

                grade = ((SCORE_BASE - days_violated) + heuristic_score);
                return grade;
            }
            catch (Exception e)
            {
                // Console.WriteLine("{0} Exception caught.", e);
                UTIL.sayDebug(e);
                throw e;
                //return REALLY_BAD_SCORE;
            }

        }//CalculateFitness
        #endregion

        #region COMPARETO
        public int CompareTo(object obj)
        {
            // Overrode normal CompareTo function so they ArrayList can be sorted by fitness
            if (!(obj is Single_Schedule))
                throw new InvalidCastException("This object is not of type Single_Schedule");

            Single_Schedule temp = (Single_Schedule)obj;
            return temp.CalculateFitness(temp.Heuristic()).CompareTo(this.CalculateFitness(this.Heuristic()));
        }//CompareTo
        #endregion

        #region SHIFT2
        /* Figure out the number of times a nurse is scheduled to work back-to-back shifts.
     * The more times this occurs, the worse the heuristic score will be.
     * */

        private int shifts2(int loop_count, ArrayList prev, ArrayList shift1, ArrayList shift2)
        {
            try
            {
                int condition_violated = 0;

                if (loop_count != 0)
                {
                    if (prev != null)
                    {
                        IEnumerator ShiftEnumPrev = prev.GetEnumerator();
                        while (ShiftEnumPrev.MoveNext())
                        {
                            if (shift1.Contains(ShiftEnumPrev.Current))
                            {
                                condition_violated++;
                            }
                        }
                    }
                }

                IEnumerator ShiftEnum = shift1.GetEnumerator();
                while (ShiftEnum.MoveNext())
                {
                    if (shift2.Contains(ShiftEnum.Current))
                    {
                        condition_violated++;
                    }
                }

                return condition_violated;
            }
            catch (Exception e)
            {
                // Console.WriteLine("{0} Exception caught.", e);
                // return REALLY_BAD_SCORE;
                UTIL.sayDebug(e);
                throw e;
            }
        }//shifts2
        #endregion

        #region SHIFT3
        /* Figure out the number of times a nurse is scheduled to work back-to-back shifts.
     * The more times this occurs, the worse the heuristic score will be.
     * */

        private int shifts3(int loop_count, ArrayList prev, ArrayList shift1, ArrayList shift2, ArrayList shift3)
        {
            try
            {
                int condition_violated = 0;

                if (loop_count != 0)
                {
                    if (prev != null)
                    {
                        IEnumerator ShiftEnumPrev = prev.GetEnumerator();
                        while (ShiftEnumPrev.MoveNext())
                        {
                            if (shift1.Contains(ShiftEnumPrev.Current))
                            {
                                condition_violated++;
                            }
                        }
                    }
                }

                IEnumerator ShiftEnum = shift1.GetEnumerator();
                while (ShiftEnum.MoveNext())
                {
                    if (shift2.Contains(ShiftEnum.Current))
                    {
                        condition_violated++;
                    }
                }

                IEnumerator ShiftEnum2 = shift2.GetEnumerator();
                while (ShiftEnum2.MoveNext())
                {
                    if (shift3.Contains(ShiftEnum2.Current))
                    {
                        condition_violated++;
                    }
                }

                return condition_violated;
            }

            catch (Exception e)
            {
                // Console.WriteLine("{0} Exception caught.", e);
                // return REALLY_BAD_SCORE;
                UTIL.sayDebug(e);
                throw e;
            }

        }//shifts3
        #endregion

        #region SHIFT4
        /* Figure out the number of times a nurse is scheduled to work back-to-back shifts.
     * The more times this occurs, the worse the heuristic score will be.
    * */

        private int shifts4(int loop_count, ArrayList prev, ArrayList shift1, ArrayList shift2, ArrayList shift3, ArrayList shift4)
        {
            try
            {
                int condition_violated = 0;

                if (loop_count != 0)
                {
                    if (prev != null)
                    {
                        IEnumerator ShiftEnumPrev = prev.GetEnumerator();
                        while (ShiftEnumPrev.MoveNext())
                        {
                            if (shift1.Contains(ShiftEnumPrev.Current))
                            {
                                condition_violated++;
                            }
                        }
                    }
                }

                IEnumerator ShiftEnum = shift1.GetEnumerator();
                while (ShiftEnum.MoveNext())
                {
                    if (shift2.Contains(ShiftEnum.Current))
                    {
                        condition_violated++;
                    }
                }

                IEnumerator ShiftEnum2 = shift2.GetEnumerator();
                while (ShiftEnum2.MoveNext())
                {
                    if (shift3.Contains(ShiftEnum.Current))
                    {
                        condition_violated++;
                    }
                }

                IEnumerator ShiftEnum3 = shift3.GetEnumerator();
                while (ShiftEnum3.MoveNext())
                {
                    if (shift4.Contains(ShiftEnum.Current))
                    {
                        condition_violated++;
                    }
                }

                return condition_violated;
            }
            catch (Exception e)
            {
                UTIL.sayDebug(e);
                //Console.WriteLine("{0} Exception caught.", e);
                //return REALLY_BAD_SCORE;
                throw e;
            }

        }//shifts4
        #endregion

        #region SHIFT5
        private int shifts5(int loop_count, ArrayList prev, ArrayList shift1, ArrayList shift2, ArrayList shift3, ArrayList shift4, ArrayList shift5)
        {
            try
            {
                int condition_violated = 0;

                if (loop_count != 0)
                {
                    if (prev != null)
                    {

                        IEnumerator ShiftEnumPrev = prev.GetEnumerator();
                        while (ShiftEnumPrev.MoveNext())
                        {
                            if (shift1.Contains(ShiftEnumPrev.Current))
                            {
                                condition_violated++;
                            }
                        }
                    }
                }

                IEnumerator ShiftEnum = shift1.GetEnumerator();
                while (ShiftEnum.MoveNext())
                {
                    if (shift2.Contains(ShiftEnum.Current))
                    {
                        condition_violated++;
                    }
                }

                IEnumerator ShiftEnum2 = shift2.GetEnumerator();
                while (ShiftEnum2.MoveNext())
                {
                    if (shift3.Contains(ShiftEnum.Current))
                    {
                        condition_violated++;
                    }
                }

                IEnumerator ShiftEnum3 = shift3.GetEnumerator();
                while (ShiftEnum3.MoveNext())
                {
                    if (shift4.Contains(ShiftEnum.Current))
                    {
                        condition_violated++;
                    }
                }

                IEnumerator ShiftEnum4 = shift4.GetEnumerator();
                while (ShiftEnum4.MoveNext())
                {
                    if (shift5.Contains(ShiftEnum.Current))
                    {
                        condition_violated++;
                    }
                }

                return condition_violated;
            }
            catch (Exception e)
            {
                // Console.WriteLine("{0} Exception caught.", e);
                //  return REALLY_BAD_SCORE;
                UTIL.sayDebug(e);
                throw e;
            }
        }//shifts4
        #endregion

        #region DAYS5
        /* Check to see if a nurse working a day that he or she does not want to work, if the nurse is working hours 
     * he or she does not prefer to work, or if the nurse is working a day he or she requested off as a vacation day.
     * */

        private int days5(DateTime start_date, int day_count, int day_of_week_count, ArrayList shift1, ArrayList shift2, ArrayList shift3, ArrayList shift4, ArrayList shift5)
        {
            try
            {
                CultureInfo enUS = new CultureInfo("en-US");

                IEnumerator ShiftEnum = shift1.GetEnumerator();
                ShiftEnum.Reset();
                int temp_nurse;
                string[] days_of_week = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
                Shift temp_shift1 = data.Shifts[0];
                Shift temp_shift2 = data.Shifts[1];
                Shift temp_shift3 = data.Shifts[2];
                Shift temp_shift4 = data.Shifts[3];
                Shift temp_shift5 = data.Shifts[4];

                int condition_violated = 0;

                while (ShiftEnum.MoveNext())
                {

                    temp_nurse = (int)ShiftEnum.Current;
                    List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();

                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift1.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift1.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }

                    List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    for (int m = 0; m < prefVacation.Count; m++)
                    {
                        if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                        {
                            condition_violated++;
                        }
                    }
                }




                ShiftEnum = shift2.GetEnumerator();
                ShiftEnum.Reset();

                while (ShiftEnum.MoveNext())
                {
                    temp_nurse = (int)ShiftEnum.Current;
                    List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();

                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift2.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift2.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }

                    List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    for (int m = 0; m < prefVacation.Count; m++)
                    {
                        if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                        {
                            condition_violated++;
                        }
                    }
                }

                ShiftEnum = shift3.GetEnumerator();
                ShiftEnum.Reset();

                while (ShiftEnum.MoveNext())
                {
                    temp_nurse = (int)ShiftEnum.Current;
                    List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();

                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift3.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift3.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }

                    List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    for (int m = 0; m < prefVacation.Count; m++)
                    {
                        if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                        {
                            condition_violated++;
                        }
                    }
                }

                ShiftEnum = shift4.GetEnumerator();
                ShiftEnum.Reset();

                while (ShiftEnum.MoveNext())
                {
                    temp_nurse = (int)ShiftEnum.Current;
                    List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();

                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift4.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift4.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }

                    List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    for (int m = 0; m < prefVacation.Count; m++)
                    {
                        if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                        {
                            condition_violated++;
                        }
                    }
                }

                ShiftEnum = shift5.GetEnumerator();
                ShiftEnum.Reset();

                while (ShiftEnum.MoveNext())
                {
                    temp_nurse = (int)ShiftEnum.Current;
                    List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();

                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift5.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift5.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }

                    List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    for (int m = 0; m < prefVacation.Count; m++)
                    {
                        if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                        {
                            condition_violated++;
                        }
                    }
                }


                day_count++;
                day_of_week_count = (day_of_week_count + 1) % 7;
                shift1.Clear();
                shift2.Clear();
                shift3.Clear();
                shift4.Clear();
                shift5.Clear();

                return condition_violated;
            }
            catch (Exception e)
            {
                // Console.WriteLine("{0} Exception caught.", e);
                // return REALLY_BAD_SCORE;
                UTIL.sayDebug(e);
                throw e;
            }

        }//days5
        #endregion

        #region DAYS4
        /* Check to see if a nurse working a day that he or she does not want to work, if the nurse is working hours 
     * he or she does not prefer to work, or if the nurse is working a day he or she requested off as a vacation day.
     * */

        private int days4(DateTime start_date, int day_count, int day_of_week_count, ArrayList shift1, ArrayList shift2, ArrayList shift3, ArrayList shift4)
        {
            try
            {
                CultureInfo enUS = new CultureInfo("en-US");

                IEnumerator ShiftEnum = shift1.GetEnumerator();
                ShiftEnum.Reset();
                int temp_nurse;
                string[] days_of_week = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
                Shift temp_shift1 = data.Shifts[0];
                Shift temp_shift2 = data.Shifts[1];
                Shift temp_shift3 = data.Shifts[2];
                Shift temp_shift4 = data.Shifts[3];

                int condition_violated = 0;

                while (ShiftEnum.MoveNext())
                {

                    temp_nurse = (int)ShiftEnum.Current;
                    List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();

                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift1.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift1.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }

                    List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    for (int m = 0; m < prefVacation.Count; m++)
                    {
                        if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                        {
                            condition_violated++;
                        }
                    }
                }

                ShiftEnum = shift2.GetEnumerator();
                ShiftEnum.Reset();

                while (ShiftEnum.MoveNext())
                {
                    temp_nurse = (int)ShiftEnum.Current;
                    List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();

                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift2.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift2.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }

                    List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    for (int m = 0; m < prefVacation.Count; m++)
                    {
                        if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                        {
                            condition_violated++;
                        }
                    }
                }

                ShiftEnum = shift3.GetEnumerator();
                ShiftEnum.Reset();

                while (ShiftEnum.MoveNext())
                {
                    temp_nurse = (int)ShiftEnum.Current;
                    List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();

                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift3.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift3.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }

                    List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    for (int m = 0; m < prefVacation.Count; m++)
                    {
                        if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                        {
                            condition_violated++;
                        }
                    }
                }

                ShiftEnum = shift4.GetEnumerator();
                ShiftEnum.Reset();

                while (ShiftEnum.MoveNext())
                {
                    temp_nurse = (int)ShiftEnum.Current;
                    List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();

                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift4.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift4.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }

                    List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    for (int m = 0; m < prefVacation.Count; m++)
                    {
                        if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                        {
                            condition_violated++;
                        }
                    }
                }

                day_count++;
                day_of_week_count = (day_of_week_count + 1) % 7;
                shift1.Clear();
                shift2.Clear();
                shift3.Clear();
                shift4.Clear();

                return condition_violated;
            }
            catch (Exception e)
            {
                //  Console.WriteLine("{0} Exception caught.", e);
                //   return REALLY_BAD_SCORE;
                UTIL.sayDebug(e);
                throw e;
            }

        }//days4
        #endregion

        #region DAYS3
        /* Check to see if a nurse working a day that he or she does not want to work, if the nurse is working hours 
    * he or she does not prefer to work, or if the nurse is working a day he or she requested off as a vacation day.
    * */

        private int days3(DateTime start_date, int day_count, int day_of_week_count, ArrayList shift1, ArrayList shift2, ArrayList shift3, List<Person> nurse_list)
        {
            try
            {
                CultureInfo enUS = new CultureInfo("en-US");

                IEnumerator ShiftEnum = shift1.GetEnumerator();
                ShiftEnum.Reset();
                int temp_nurse = 0;
                string[] days_of_week = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

                /* Won't work until there are shifts in the database
                Shift temp_shift1 = data.Shifts[0];
                Shift temp_shift2 = data.Shifts[1];
                Shift temp_shift3 = data.Shifts[2];
                */

                int condition_violated = 0;

                while (ShiftEnum.MoveNext())
                {

                    temp_nurse = (int)ShiftEnum.Current;
                    //List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();
                    /*
                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift1.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift1.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }
                    */

                    //List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    //for (int m = 0; m < prefVacation.Count; m++)
                    //{
                    //if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                    //{
                    //condition_violated++;
                    //}
                    //}
                }

                ShiftEnum = shift2.GetEnumerator();
                ShiftEnum.Reset();

                while (ShiftEnum.MoveNext())
                {
                    temp_nurse = (int)ShiftEnum.Current;
                    //List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();

                    /*
                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift2.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift2.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }
                    */

                    //List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    //for (int m = 0; m < prefVacation.Count; m++)
                    //{
                    //if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                    //{
                    // condition_violated++;

                    //}
                }

                ShiftEnum = shift3.GetEnumerator();
                ShiftEnum.Reset();

                while (ShiftEnum.MoveNext())
                {
                    temp_nurse = (int)ShiftEnum.Current;
                    //List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();
                    /*
                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift3.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift3.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }
                     */

                    //List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    //for (int m = 0; m < prefVacation.Count; m++)
                    //{
                    //if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                    //{
                    // condition_violated++;
                    //}
                    //}
                }

                //shift1.Clear();
                //shift2.Clear();
                //shift3.Clear();

                return condition_violated;
            }
            catch (Exception e)
            {
                // Console.WriteLine("{0} Exception caught.", e);
                //return REALLY_BAD_SCORE;
                UTIL.sayDebug(e);
                throw e;
            }
        }//days3

        #endregion

        #region DAYS2
        /* Check to see if a nurse working a day that he or she does not want to work, if the nurse is working hours 
    * he or she does not prefer to work, or if the nurse is working a day he or she requested off as a vacation day.
    * */

        private int days2(DateTime start_date, int day_count, int day_of_week_count, ArrayList shift1, ArrayList shift2)
        {
            try
            {
                CultureInfo enUS = new CultureInfo("en-US");
                IEnumerator ShiftEnum = shift1.GetEnumerator();
                ShiftEnum.Reset();

                int condition_violated = 0;
                int temp_nurse = 0;
                string[] days_of_week = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
                Shift temp_shift1 = data.Shifts[0];
                Shift temp_shift2 = data.Shifts[1];

                while (ShiftEnum.MoveNext())
                {

                    temp_nurse = (int)ShiftEnum.Current;
                    List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();

                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift1.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift1.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }

                    List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    for (int m = 0; m < prefVacation.Count; m++)
                    {
                        if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                        {
                            condition_violated++;
                        }
                    }
                }

                ShiftEnum = shift2.GetEnumerator();
                ShiftEnum.Reset();

                while (ShiftEnum.MoveNext())
                {
                    temp_nurse = (int)ShiftEnum.Current;
                    List<Shift> pref_shifts = data.Persons[temp_nurse].loadPreferredShifts();

                    for (int m = 0; m < pref_shifts.Count; m++)
                    {
                        Shift temp_shift = pref_shifts.ElementAt(m);

                        if (temp_shift.StartTime == temp_shift2.StartTime)
                        {
                            condition_violated++;
                        }

                        if (temp_shift.DayOfWeek.Equals(temp_shift2.DayOfWeek))
                        {
                            condition_violated++;
                        }

                    }

                    List<Day> prefVacation = data.Persons[temp_nurse].loadVacationDays();
                    for (int m = 0; m < prefVacation.Count; m++)
                    {
                        if (start_date.AddDays(day_count).Equals(prefVacation.ElementAt(m).DateTime))
                        {
                            condition_violated++;
                        }
                    }

                    shift1.Clear();
                    shift2.Clear();
                }

                return condition_violated;
            }
            catch (Exception e)
            {
                //  Console.WriteLine("{0} Exception caught.", e);
                //   return REALLY_BAD_SCORE;
                UTIL.sayDebug(e);
                throw e;
            }
        }//days2
        #endregion


        #region MUTATE

        public ArrayList Mutate(int begin, int pivot)
        {
            // Return part of the array: from the beginning to the random pivot point
            return TheArray.GetRange(begin, pivot);
        }

        #endregion

        #region SETARRAY

        public void SetArray(ArrayList rest, int pivot)
        {
            // Mate two arrays using a random pivot point
            TheArray.RemoveRange(0, pivot);
            TheArray.InsertRange(0, rest);
        }

        #endregion

        #region TOSCHEDULE
        /* Convert a Single_Schedule into the form of a Schedule which will be displayed in the interface */

        ///* Not finished yet...
        public Schedule ToSchedule()
        {
            try
            {
                #region vars
                List<Person> nurse_list = new List<Person>();
                nurse_list = data.Persons;//Person.loadAllActiveNurses();
                DateTime start = new DateTime();
                DateTime end = new DateTime();
                start = data.StartDate;
                end = start.AddDays(data.NumDays);
                int day_pivot = 0;
                int pivot = 0;
                int shift_pivot = 0;
                int num_departments = data.Departments.Count;
                int department_nurse_total = 0;

                // Assume shifts=3
                //int shifts = data.Shifts.Count;
                int shifts = 3;

                for (int k = 0; k < num_departments; k++)
                {
                    department_nurse_total += data.Departments[k].PeopleNeeded;
                }//for
                int max = department_nurse_total * shifts;
                int dept_max = max / num_departments;
                int shift_max = dept_max / shifts;
                int space_between = 0;
                int shift_count = 0;
                #endregion
                // Schedule schedule = new Schedule(start, end);
                Schedule schedule = Schedule.getWeeklyTemplateSchedule();
                schedule.StartDate = data.StartDate;

                #region junk
                /*
            List<Day> day_list = new List<Day>();

            for (int u = 0; u < data.NumDays; u++)
            {
                day_list.Add(new Day());
            }
            schedule.Days = day_list;
             * 
             */
                #endregion
                schedule.Grade = grade;

                string day_of_week = start.DayOfWeek.ToString();

                #region switch
                int start_DOW = 0;
                switch (day_of_week)
                {
                    case "Sunday":
                        start_DOW = 0;
                        break;
                    case "Monday":
                        start_DOW = 1;
                        break;
                    case "Tuesday":
                        start_DOW = 2;
                        break;
                    case "Wednesday":
                        start_DOW = 3;
                        break;
                    case "Thursday":
                        start_DOW = 4;
                        break;
                    case "Friday":
                        start_DOW = 5;
                        break;
                    case "Saturday":
                        start_DOW = 6;
                        break;
                    default:
                        start_DOW = 0;
                        break;
                }
                #endregion

                /* Overview: Change the Single_Schedule (using an int array to represent a schedule) into a Schedule.
             * For each day, cycle through departments. Assign the daily shifts for each department.
             * Also, assign values to DateTime's and update SchedulePointers, etc.
             */


                for (int d = 0; d < data.NumDays; d++)
                {
                    ArrayList arrayDay = TheArray.GetRange(day_pivot, max);
                    IEnumerator Enum = arrayDay.GetEnumerator();
                    Enum.Reset();

                    schedule.Days[d].DateTime = start.AddDays(d);
                    string current_date = ((start.AddDays(d)).DayOfWeek).ToString();
                    schedule.Days[d].DayOfWeek.setDayOfWeek(current_date);




                    for (int de = 0; de < num_departments; de++)
                    {

                        //for (int r = 0; r < shifts; r++)
                        //{
                        // schedule.Days[d].Departments[de].Shifts.Add(new Shift());

                        //}
                        //schedule.Days[d].Departments[de].Shifts = schedule.Days[d].Departments[de].shiftsOnThisDay(start.AddDays(d));
                        //schedule.writeOutObjectTree(0, 0);
                        schedule.Days[d].Departments[de].SchedulePointer = schedule;

                        if (data.Shifts.Count == 0)
                        {
                            //List<Shift> shift_list = new List<Shift>();
                            //Shift shift = new Shift();
                            //shift.SchedulePointer = schedule;


                            //shift.DayOfWeek.setDayOfWeek(current_date);
                            //shift_list.Add(shift);
                            // for (int i = 0; i < shifts - 1; i++)
                            // {
                            //     shift_list.Add(shift.Clone());
                            // }
                            // schedule.Days[d].Departments[de].Shifts = shift_list;
                        }
                        shift_count = 0;
                        //schedule.Days[d].Departments[de].Shifts = schedule.Days[d].Departments[de].shiftsOnThisDay(start.AddDays(d));
                        while (shift_count < shifts)
                        {

                            space_between = department_nurse_total;
                            int[] cur = new int[data.Departments[de].PeopleNeeded];
                            for (int b = 0; b < data.Departments[de].PeopleNeeded; b++)
                            {
                                cur[b] = (int)arrayDay[shift_pivot];
                            }

                            /* List<Person> person_list = new List<Person>();
                             for (int g = 0; g < data.Departments[de].PeopleNeeded; g++)
                             {
                                 person_list.Add(new Person());
                             }
                             */

                            //schedule.Days[d].Departments[de].Shifts[shift_count].Persons=
                            for (int z = 0; z < data.Departments[de].PeopleNeeded; z++)
                            {
                                //schedule.Days[d].Departments[de].Shifts[shift_count].Persons[z] = nurse_list[cur[z]];
                                schedule.Days[d].Departments[de].shiftsOnThisDay(schedule.Days[d].DateTime)[shift_count].Persons.Add(nurse_list[cur[z]]);
                            }



                            shift_pivot += space_between;
                            shift_count++;
                        }
                        space_between = 0;
                        shift_pivot = 0;

                        for (int t = 0; t <= de; t++)
                            shift_pivot += data.Departments[t].PeopleNeeded;

                    }

                    shift_pivot = 0;
                    day_pivot += max;
                }

                return schedule;
            }


            catch (Exception e)
            {
                UTIL.sayDebug(e);
                throw e;
                //Console.WriteLine("{0} Exception caught.", e);
                //return null;
            }
        }
        #endregion


    }

}

